#ifndef _SYS_SEM_H
#define _SYS_SEM_H

#include <string>
#include <atomic>

#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
using handle_t = HANDLE;
#endif

#if defined(__APPLE__) || defined(__linux__)
#include <semaphore.h>
using handle_t = sem_t *;
#endif

class SystemSemaphore final
{
public:
    enum AccessMode
    {
        Open = 0,
        Create
    };
    SystemSemaphore(const std::string &key, int initialValue, AccessMode mode);
    ~SystemSemaphore();

    bool Acquire();
    bool Release(int n = 1);

protected:
    bool OpenSemaphore();
    void CloseSemaphore();
    bool ModifySemaphore(int count);

private:
    SystemSemaphore(const SystemSemaphore &) = delete;
    SystemSemaphore &operator=(const SystemSemaphore &) = delete;

private:
    handle_t handle{nullptr};
    std::string name;
    int initialValue{0};
    AccessMode mode{Open};
    bool createdSemaphore{false};
};

#endif // _SYS_SEM_H